package com.springlearn.springsourcecode.chap15;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;

import org.springframework.aop.framework.ProxyFactory;
import org.springframework.aop.support.DefaultPointcutAdvisor;

/**
 * @author wtcode
 * @Description
 * @date 2025/4/7 - 16:35
 */
public class A15 {

    @Aspect
    static class MyAspect{

        @Before("execution(* foo())")
        public void before(){
            System.out.println("前置增强");
        }

        @After("execution(* foo())")
        public void after(){
            System.out.println("后置增强");
        }
    }


    public static void main(String[] args) {

        /*
         * aspect = 通知1（advice） + 切点1（pointcut）
         *          通知2（advice） + 切点2（pointcut）
         *          通知3（advice） + 切点3（pointcut）
         *
         * advisor = 更细粒度的切面，包含一个通知和切点
         */

        // 备好切点
        AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
        pointcut.setExpression("execution(* foo())");
        // 备好通知
        MethodInterceptor advice = invocation -> {
            System.out.println("before....");
            Object proceed = invocation.proceed();
            System.out.println("after....");
            return proceed;
        };
        // 备好切面
        DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor(pointcut,advice);

        // 创建代理
        // 1 proxyTargetClass = false ， 目标实现了接口，用JDK实现
        // 2 proxyTargetClass = false ， 目标实现没有实现接口，用Cglib实现
        // 3 proxyTargetClass = true ， 用Cglib实现
        Target1 target = new Target1();
        ProxyFactory proxyFactory = new ProxyFactory();
        proxyFactory.setTarget(target);
        proxyFactory.setInterfaces(I1.class.getInterfaces());
        proxyFactory.setProxyTargetClass(true);
        proxyFactory.addAdvisor(advisor);
        I1 proxy = (I1)proxyFactory.getProxy();
        System.out.println(proxy.getClass());
        proxy.foo();
        proxy.bar();

    }

    interface I1{
        void foo();
        void bar();
    }


    static class Target1 implements I1{

        @Override
        public void foo() {
            System.out.println("Target1 foo");
        }

        @Override
        public void bar() {
            System.out.println("Target1 bar");
        }
    }


    static class Target2 implements I1{

        @Override
        public void foo() {
            System.out.println("Target2 foo");
        }

        @Override
        public void bar() {
            System.out.println("Target2 bar");
        }
    }

}
